package Triangulation.minimalityMetrics;

import static tools.Tool.*;
import datatypes.Edge;
import datatypes.Triangle;

public class LongestBaseToHeightRatioMetric extends AbstractMinimalityMetric
implements MinimumTriangleSumMetric {
	
	/**
	 * The longer length divided by the shorter length.
	 * Hence, the value is >= 1.0.
	 * @param length1
	 * @param length2
	 * @return
	 */
	private double ratio (double length1, double length2) {
		return length1 > length2 ? length1 / length2 : length2 / length1;
	}
	
	private double ratioForTriangles(Triangle t1, Triangle t2) {
		Edge longestEdgeT1 = t1.getLongestEdge();
		Edge longestEdgeT2 = t2.getLongestEdge();
		
		double longestEdgeLengthT1 = longestEdgeT1.getLength();
		double longestEdgeLengthT2 = longestEdgeT2.getLength();
		
		// summing up the ratios of both triangles:
		double ratio = ratio(longestEdgeLengthT1, t1.height(longestEdgeT1));
		ratio += ratio(longestEdgeLengthT2, t2.height(longestEdgeT2));
		return ratio;
	}
	
	@Override
	public boolean edgeIsLocallyMinimal(Edge sharedEdge, Triangle t1, Triangle t2) {
		if ( ! quadIsConvex(t1, t2, sharedEdge)) {
			// If quad is NOT convex, then sharedEdge is locally minimal.
			// See "A Large Subgraph of the Minimum Weight Triangulation" 
			// p.291, 1.3
			return true;
		}
		double ratioExistingQuad = ratioForTriangles(t1, t2);
		
		Edge perpendicular = new Edge(t1.getVertexNotOnEdge(sharedEdge), t2.getVertexNotOnEdge(sharedEdge));
		Edge e2t1 = new Edge(perpendicular.getVertex1(), sharedEdge.getVertex1());
		Edge e3t1 = new Edge(perpendicular.getVertex2(), sharedEdge.getVertex1());
		Edge e2t2 = new Edge(perpendicular.getVertex1(), sharedEdge.getVertex2());
		Edge e3t2 = new Edge(perpendicular.getVertex2(), sharedEdge.getVertex2());
		
		try {
			t1 = new Triangle(perpendicular, e2t1, e3t1, false);
			t2 = new Triangle(perpendicular, e2t2, e3t2, false);
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		double ratioFlippedQuad = ratioForTriangles(t1, t2);
		
		return ratioExistingQuad <= ratioFlippedQuad;
	}

	@Override
	public double getAngleForDiamondProperty() {
		// Diamond property not known to be applicable.
		return -1;
	}

	@Override
	public String getName() {
		return "longest base to height ratio";
	}

	@Override
	public double getTriangleWeight(Triangle t)
	{
		Edge longestEdge = t.getLongestEdge();
		return ratio(longestEdge.getLength(), t.height(longestEdge));
	}

}
